using System;
using System.Collections.Generic;
using System.Linq;
using System.Data.Objects;
using System.Security.Cryptography;
using System.ComponentModel.DataAnnotations;

namespace GameDb.Entities
{
	public class GameMatch
	{
		public GameMatch()
		{
			this.MatchPieces = new List<MatchPiece>();
			this.MatchPlayers = new List<MatchPlayer>();
			this.MatchTurns = new List<MatchTurn>();
		}

		public int GameMatchId { get; set; }
		public DateTime StartDate { get; set; }
		public int NumberOfTrayPieces {get; set;}
		public int CountOfEachPieceType {get; set; }
		public virtual Game Game { get; set; }
		public virtual ICollection<MatchPiece> MatchPieces { get; set; }
		public virtual ICollection<MatchPlayer> MatchPlayers { get; set; }
        public virtual ICollection<MatchTurn> MatchTurns { get; set; }

        public MatchPiece[] SelectPieces(MatchPlayerTurn playerTurn, int pieceCount)
        {
            var outPieces = new List<MatchPiece>();
            for (var ndx = 0; ndx < pieceCount; ndx++)
            {
                var remainingPieces = PiecesInBag().ToList();
                if (remainingPieces.Count > 0)
                {
                    var bytes = new byte[sizeof(int)];
                    RNGCryptoServiceProvider Gen = new RNGCryptoServiceProvider();
                    Gen.GetBytes(bytes);
                    var seed = BitConverter.ToInt32(bytes, 0);
                    var rnd = new Random((int)seed);
                    var pieceNo = rnd.Next(remainingPieces.Count);
                    var pieceSel = remainingPieces[pieceNo];
                    outPieces.Add(pieceSel);
                    pieceSel.MatchPlayerTurn = playerTurn;
                }
            }

            return outPieces.ToArray();
        }

        private string _playerDisplay;
        [NotMapped]
        public string PlayerDisplay
        {
            get
            {
                if (_playerDisplay == null)
                    _playerDisplay = string.Join(",", MatchPlayers.Select(mp => mp.User.Username).ToArray());
                return _playerDisplay;
            }
            set
            {
                _playerDisplay = value;
            }
        }
		public MatchTurn CurrentTurn
		{
			get
			{
                var qry = MatchTurns.Where(mt => mt.StartDate != null && mt.CompleteDate == null);
                if (qry.Count() == 0)
                    return null;
                return qry.Single();
			}
		}
		
		public IQueryable<MatchPiece> TrayPieces()
		{
			return MatchPieces.Where(mp => mp.BoardXpos == null && mp.BoardYpos == null
                        && mp.MatchPlayerTurn != null).AsQueryable();
		}
		
        public IQueryable<MatchPiece> PiecesInBag()
		{
            return MatchPieces.Where(mp => mp.BoardXpos == null && mp.BoardYpos == null
                && mp.MatchPlayerTurn == null).AsQueryable();
		}

        public IQueryable<MatchPiece> PiecesOnBoard
        {
            get
            {
                return MatchPieces.Where(mp => mp.BoardXpos != null && mp.BoardYpos != null).AsQueryable();
            }
        }

        public static GameMatch GameMatchFromId(GameDbContext ctx, int gameMatchId)
		{
			return ctx.GameMatches.Where(gm => gm.GameMatchId == gameMatchId).Single();
		}

		public MatchPlayer GetMatchPlayer(GameDbContext ctx, User user)
		{
			return MatchPlayers.Where(mp => mp.UserId == user.UserId).Single();
		}
	}
}

